#include "epaper_driver.h"
#include "main.h"

PAINT Paint;
// 写入一个命令
void EPA_WR_REG(uint8_t reg)
{
  EPA_CS_CLR;
  EPA_DC_CLR;
  SPIv_WriteData(reg);
  EPA_CS_SET;
}

// 写入数据
void EPA_WR_DATA8(uint8_t dat)
{
  EPA_CS_CLR;
  EPA_DC_SET;
  SPIv_WriteData(dat);
  EPA_CS_SET;
}
// 检查忙状态
void Epaper_READBUSY(void)
{
  while (1)
  {
    if (EPA_BUSY == 0)
    {
      break;
    }
  }
}

void EPD_Update(void)
{
  EPA_WR_REG(0x22); // Display Update Control
  EPA_WR_DATA8(0xF7);
  // EPA_WR_DATA8(0xFF);
  EPA_WR_REG(0x20); // Activate Display Update Sequence
  Epaper_READBUSY();
}

// 初始化屏幕
void EPD_GUIInit(void)
{
  EPA_RES_CLR;   // Module reset
  HAL_Delay(20); // At least 10ms delay
  EPA_RES_SET;
  HAL_Delay(20); // At least 10ms delay

  Epaper_READBUSY();
  EPA_WR_REG(0x12); // SWRESET
  Epaper_READBUSY();

  EPA_WR_REG(0x01); // Driver output control
  EPA_WR_DATA8(0xC7);
  EPA_WR_DATA8(0x00);
  EPA_WR_DATA8(0x01);

  EPA_WR_REG(0x11); // data entry mode
  EPA_WR_DATA8(0x01);

  EPA_WR_REG(0x44); // set Ram-X address start/end position
  EPA_WR_DATA8(0x00);
  EPA_WR_DATA8(0x18); // 0x0F-->(15+1)*8=128

  EPA_WR_REG(0x45);   // set Ram-Y address start/end position
  EPA_WR_DATA8(0xC7); // 0xF9-->(249+1)=250
  EPA_WR_DATA8(0x00);
  EPA_WR_DATA8(0x00);
  EPA_WR_DATA8(0x00);

  EPA_WR_REG(0x3C); // BorderWavefrom
  EPA_WR_DATA8(0x05);

  //  EPA_WR_REG(0x21); //  Display update control
  //  EPA_WR_DATA8(0x00);
  //  EPA_WR_DATA8(0x80);

  EPA_WR_REG(0x18); // Read built-in temperature sensor
  EPA_WR_DATA8(0x80);

  EPA_WR_REG(0x4E); // set RAM x address count to 0;
  EPA_WR_DATA8(0x00);
  EPA_WR_REG(0x4F); // set RAM y address count to 0X199;
  EPA_WR_DATA8(0xC7);
  EPA_WR_DATA8(0x00);

  Epaper_READBUSY();
}

void Paint_NewImage(uint8_t *image, uint16_t Width, uint16_t Height, uint16_t Rotate, uint16_t Color)
{
  Paint.Image = 0x00;
  Paint.Image = image;

  Paint.WidthMemory = Width;
  Paint.HeightMemory = Height;
  Paint.Color = Color;
  Paint.WidthByte = (Width % 8 == 0) ? (Width / 8) : (Width / 8 + 1);
  Paint.HeightByte = Height;
  Paint.Rotate = Rotate;
  if (Rotate == ROTATE_0 || Rotate == ROTATE_180)
  {
    Paint.Width = Width;
    Paint.Height = Height;
  }
  else
  {
    Paint.Width = Height;
    Paint.Height = Width;
  }
}

void Paint_SetPixel(uint16_t Xpoint, uint16_t Ypoint, uint16_t Color)
{
  uint16_t X, Y;
  uint32_t Addr;
  uint8_t Rdata;
  switch (Paint.Rotate)
  {
  case 0:
    X = Xpoint;
    Y = Ypoint;
    break;
  case 90:
    X = Paint.WidthMemory - Ypoint - 1;
    Y = Xpoint;
    break;
  case 180:
    X = Paint.WidthMemory - Xpoint - 1;
    Y = Paint.HeightMemory - Ypoint - 1;
    break;
  case 270:
    X = Ypoint;
    Y = Paint.HeightMemory - Xpoint - 1;
    break;
  default:
    return;
  }
  Addr = X / 8 + Y * Paint.WidthByte;
  Rdata = Paint.Image[Addr];
  if (Color == BLACK)
  {
    Paint.Image[Addr] = Rdata & ~(0x80 >> (X % 8)); // 将对于数据至0
  }
  else
    Paint.Image[Addr] = Rdata | (0x80 >> (X % 8)); // 将对于数据至1
}

// 清屏函数
void EPA_Clear(uint16_t Color)
{
  uint16_t X, Y;
  uint32_t Addr;
  for (Y = 0; Y < Paint.HeightByte; Y++)
  {
    for (X = 0; X < Paint.WidthByte; X++)
    { // 8 pixel =  1 byte
      Addr = X + Y * Paint.WidthByte;
      Paint.Image[Addr] = Color;
    }
  }
}

// 画点函数
void EPA_DrawPoint(uint16_t Xpoint, uint16_t Ypoint, uint16_t Color)
{
  Paint_SetPixel(Xpoint - 1, Ypoint - 1, Color);
}

// 更新到显存
void EPA_Display(unsigned char *Image)
{
  unsigned int Width, Height, i, j;
  uint32_t k = 0;
  Width = 200;
  Height = 25;
  EPA_WR_REG(0x24);
  for (j = 0; j < Height; j++)
  {
    for (i = 0; i < Width; i++)
    {
      EPA_WR_DATA8(Image[k]);
      k++;
    }
  }
  EPD_Update();
}

/**
 * @description: 显示图片
 * @param {uint16_t} x 起点坐标 x
 * @param {uint16_t} y 起点坐标 y
 * @param {uint16_t} sizex 图片宽度 x
 * @param {uint16_t} sizey 图片长度 y
 * @param {uint8_t} BMP 图片数组
 * @param {uint16_t} Color 颜色
 * @return {*}
 */
void EPA_ShowPicture(uint16_t x, uint16_t y, uint16_t sizex, uint16_t sizey, const uint8_t BMP[], uint16_t Color)
{
  uint16_t j = 0;
  uint16_t i, n, temp, m;
  uint16_t x0, y0;
  x += 1, y += 1, x0 = x, y0 = y;
  sizey = sizey / 8 + ((sizey % 8) ? 1 : 0);
  for (n = 0; n < sizey; n++)
  {
    for (i = 0; i < sizex; i++)
    {
      temp = BMP[j];
      j++;
      for (m = 0; m < 8; m++)
      {
        if (temp & 0x01)
          EPA_DrawPoint(x, y, Color);
        else
          EPA_DrawPoint(x, y, !Color);
        temp >>= 1;
        y++;
      }
      x++;
      if ((x - x0) == sizex)
      {
        x = x0;
        y0 = y0 + 8;
      }
      y = y0;
    }
  }
}